package com.vois.jack.btmgr.devices.WLSPPDev;

import android.os.Bundle;
import android.os.Message;

import com.vois.jack.btmgr.classicbase.BtDevCommonMsg;
import com.vois.jack.btmgr.classicbase.BtDevConstant;
import com.vois.jack.btmgr.classicbase.BtRecorderInterface;
import com.vois.jack.btmgr.classicbase.BtScoRecorder;
import com.vois.jack.btmgr.classicbase.DefaultSppBtDevice;
import com.vois.jack.btmgr.common.IBtConstants;
import com.vois.jack.btmgr.util.Logger;

import java.util.UUID;

public class WLSPPDev extends DefaultSppBtDevice {
    private Logger logger = Logger.getLogger(WLSPPDev.class);
    private int curCmdContentLen;
    private int curCmdContentOffset;
    private byte curCmd;
    private int curSeq;
    private short curChecksum;
    private byte[] cmdData;

    private void processCmd(byte cmdType, byte[] data, int dataSize) {
        logger.d("cmdType: " + String.format("%x", cmdType));
        switch (cmdType) {
            case (byte)0xFF: {
                logger.d("get len " + dataSize + " data");
                logger.dumpArray(data, dataSize);

                if (data[0] == (byte)0x40) {
                    Message message = Message.obtain();
                    Bundle bundle = new Bundle();
                    if (data[1] == 0x01) {
                        message.what = BtDevCommonMsg.BT_DEV_COMMON_KEY_PRESSED.getValue();
                        bundle.putInt(BtDevConstant.EXTRA_KEY_CODE, BtDevConstant.BT_KEY_CODE_PTT);
                        message.setData(bundle);
                    }else {
                        message.what = BtDevCommonMsg.BT_DEV_COMMON_KEY_RELEASED.getValue();
                        bundle.putInt(BtDevConstant.EXTRA_KEY_CODE, BtDevConstant.BT_KEY_CODE_PTT);
                        message.setData(bundle);
                    }

                    if (getListener() != null) {
                        getListener().onMessage(this, message);
                    }
                }
            }
            break;

            case (byte)0xEE: {
                if (data[0] == (byte)0x21) {
                    final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
                            'E', 'F' };
                    if (dataSize > 16) {
                        char[] out = new char[32];
                        for (int i = 1, j = 0; i < 17; i++) {
                            out[j++] = DIGITS_UPPER[(0xF0 & data[i]) >>> 4];
                            out[j++] = DIGITS_UPPER[0x0F & data[i]];
                        }

                        logger.d("get UUID:" + new String(out));

                        Message message = Message.obtain();
                        message.what = BtDevCommonMsg.BT_DEV_GET_VALIDATE_DATA_RET.getValue();
                        Bundle bundle = new Bundle();
                        bundle.putString(BtDevConstant.EXTRA_SEQID, new String(out));
                        bundle.putString(BtDevConstant.EXTRA_VENDOR, "100A");
                        message.setData(bundle);
                        if (getListener() != null) {
                            getListener().onMessage(this, message);
                        }
                    }

                }
            }
            break;

            default: {
                logger.d("other command got!!!!!!!!.............");
            }
            break;
        }
    }

    @Override
    public int getSampleRate() {
        return 16000;
    }

    @Override
    protected int processRecvInitState(byte[] data, int dataSize, int curPos) {
        while (curPos + 6 < dataSize) {
            if (data[curPos] == (byte)0xA4 && data[curPos + 1] == (byte)0xB4) {
                curChecksum = 0;
                curCmd = data[curPos + 2];
                curChecksum += (short)((short)curCmd & 0xFF);
                curChecksum += (short)((short)data[curPos + 3] & 0xFF);
                curChecksum += (short)((short)data[curPos + 4] & 0xFF);
                curCmdContentLen = (data[curPos + 3] & 0xFF);
                curCmdContentOffset = 0;
                setRecvState(false);
                if (curCmdContentLen > 0) {
                    cmdData = new byte[curCmdContentLen];
                }

                return curPos + 5;
            }

            curPos++;
        }

        return curPos;
    }

    @Override
    protected int processRecvPayloadState(byte[] data, int dataSize, int curPos) {
        int dataShouldRead;
        int curRecvSize = getCurRecvSize();
        logger.d("curCmdContentOffset:" + curCmdContentOffset + " curCmdContentLen:" + curCmdContentLen);
        logger.d("curPos:" + curPos + " curRecvSize:" + curRecvSize);
        while (curPos < curRecvSize) {
            if (curCmdContentOffset < curCmdContentLen) {
                if ((curCmdContentLen - curCmdContentOffset) <= dataSize - curPos) {
                    dataShouldRead = curCmdContentLen - curCmdContentOffset;
                } else {
                    dataShouldRead = dataSize - curPos;
                }

                logger.d("dataShouldRead:" + dataShouldRead);

                System.arraycopy(data, curPos, cmdData, curCmdContentOffset, dataShouldRead);
                curCmdContentOffset += dataShouldRead;
                curPos += dataShouldRead;
            } else {
                if (curPos + 2 <= dataSize) {
                    short recvChecksum;
                    recvChecksum = (short)((short)data[curPos] & 0xFF);
                    recvChecksum = (short)((recvChecksum << 8) + ((short)data[curPos + 1] & 0xFF));
                    for (int i = 0; i < curCmdContentLen; i++) {
                        curChecksum += (short)((short)cmdData[i] & 0xFF);
                    }

                    logger.d("recvChecksum: " + recvChecksum + " curChecksum:" + curChecksum);
                    if (recvChecksum == curChecksum) {
                        processCmd(curCmd, cmdData, curCmdContentLen);
                    }

                    curChecksum = 0;
                    curCmdContentLen = 0;
                    curCmd = 0;
                    cmdData = null;
                    setRecvState(true);
                    curPos += 2;
                    logger.d("current curpos:" + curPos);
                }else {
                    break;
                }
            }
        }

        logger.d("curPos: " + curPos);

        return curPos;
    }

    @Override
    public BtRecorderInterface getRecorder(int recorderType) {
        return new BtScoRecorder();
    }

    @Override
    protected UUID getSppConnectUUID() {
        return UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    }

    @Override
    public String getDeviceType() {
        return "Device for WL Protocol1.0";
    }

    @Override
    public String getProtocolName() {
        return IBtConstants.PROTOCOL_VOIS;
    }

    @Override
    public int getDefaultRecorderType() {
        return SCO_RECORDER;
    }

    @Override
    public void getValidateData() {
        byte[] content = new byte[1];
        content[0] = (byte) 0x21;
        sendCommand((byte)0xEF, content, 1);
    }

    private void sendCommand(byte cmd, byte[] payload, int payloadLen) {
        byte[] dataSend = new byte[payloadLen + 7];
        short checksum = 0;

        dataSend[0] = (byte) 0xA4;
        dataSend[1] = (byte) 0xB4;
        dataSend[2] = cmd;
        dataSend[3] = (byte)payloadLen;
        dataSend[4] = 0;
        System.arraycopy(payload, 0, dataSend, 5, payloadLen);

        for (int i = 2; i < payloadLen + 5; i++) {
            checksum += dataSend[i];
        }

        dataSend[5 + payloadLen] = (byte) ((checksum & 0xFF00) >> 8);
        dataSend[6 + payloadLen] = (byte) ((checksum & 0x00FF));

        logger.dumpArray(dataSend, payloadLen + 7);
        putSppSendData(dataSend, payloadLen + 7);
    }

    @Override
    public void setSeqID(String seqID) {

    }

    @Override
    public void getVendor() {
    }

    @Override
    public void getVersion() {
    }
}
